﻿using System;
using HslCommunication.Reflection;

namespace HslCommunication.LogNet
{
	/// <summary>
	/// 一个按照实际进行数据分割的辅助基类，可以用于实现对某个的API按照每天进行调用次数统计，也可以实现对某个设备数据按照天进行最大最小值均值分析，这些都是需要继承实现。<br />
	/// An auxiliary base class that divides the data according to the actual data can be used to implement statistics on the number of calls per day for a certain API, and it can also implement the maximum and minimum average analysis of a certain device data according to the day. These all need to be inherited. .
	/// </summary>
	/// <typeparam name="T">统计的数据类型</typeparam>
	// Token: 0x020000D8 RID: 216
	public class LogStatisticsBase<T>
	{
		/// <summary>
		/// 实例化一个新的数据统计内容，需要指定当前的时间统计方式，按小时，按天，按月等等，还需要指定统计的数据数量，比如按天统计30天。<br />
		/// To instantiate a new data statistics content, you need to specify the current time statistics method, by hour, by day, by month, etc., 
		/// and also need to specify the number of statistics, such as 30 days by day.
		/// </summary>
		/// <param name="generateMode">时间的统计方式</param>
		/// <param name="arrayLength">数据的数量信息</param>
		// Token: 0x0600110C RID: 4364 RVA: 0x00061A50 File Offset: 0x0005FC50
		public LogStatisticsBase(GenerateMode generateMode, int arrayLength)
		{
			this.generateMode = generateMode;
			this.arrayLength = arrayLength;
			this.statistics = new T[arrayLength];
			this.lastDataMark = this.GetDataMarkFromDateTime(DateTime.Now);
			this.lockStatistics = new object();
		}

		/// <summary>
		/// 获取当前的统计类信息时间统计规则<br />
		/// Get the current statistical information time statistics rule
		/// </summary>
		// Token: 0x1700025E RID: 606
		// (get) Token: 0x0600110D RID: 4365 RVA: 0x00061AB9 File Offset: 0x0005FCB9
		public GenerateMode GenerateMode
		{
			get
			{
				return this.generateMode;
			}
		}

		/// <summary>
		/// 获取当前的统计类信息的数据总量<br />
		/// Get the total amount of current statistical information
		/// </summary>
		// Token: 0x1700025F RID: 607
		// (get) Token: 0x0600110E RID: 4366 RVA: 0x00061AC1 File Offset: 0x0005FCC1
		public int ArrayLength
		{
			get
			{
				return this.arrayLength;
			}
		}

		/// <summary>
		/// 重置当前的统计信息，需要指定统计的数据内容，最后一个数据的标记信息，本方法主要用于还原统计信息<br />
		/// To reset the current statistical information, you need to specify the content of the statistical data, 
		/// and the tag information of the last data. This method is mainly used to restore statistical information
		/// </summary>
		/// <param name="statistics">统计结果数据信息</param>
		/// <param name="lastDataMark">最后一次标记的内容</param>
		// Token: 0x0600110F RID: 4367 RVA: 0x00061ACC File Offset: 0x0005FCCC
		public void Reset(T[] statistics, long lastDataMark)
		{
			bool flag = statistics.Length > this.arrayLength;
			if (flag)
			{
				Array.Copy(statistics, statistics.Length - this.arrayLength, this.statistics, 0, this.arrayLength);
			}
			else
			{
				bool flag2 = statistics.Length < this.arrayLength;
				if (flag2)
				{
					Array.Copy(statistics, 0, this.statistics, this.arrayLength - statistics.Length, statistics.Length);
				}
				else
				{
					this.statistics = statistics;
				}
			}
			this.arrayLength = statistics.Length;
			this.lastDataMark = lastDataMark;
		}

		/// <summary>
		/// 新增一个统计信息，将会根据当前的时间来决定插入数据位置，如果数据位置发生了变化，则数据向左发送移动。如果没有移动或是移动完成后，最后一个数进行自定义的数据操作<br />
		/// Adding a new statistical information will determine the position to insert the data according to the current time. If the data position changes, 
		/// the data will be sent to the left. If there is no movement or after the movement is completed, Custom data operations on the last number
		/// </summary>
		/// <param name="newValue">增对最后一个数的自定义操作</param>
		// Token: 0x06001110 RID: 4368 RVA: 0x00061B54 File Offset: 0x0005FD54
		protected void StatisticsCustomAction(Func<T, T> newValue)
		{
			object obj = this.lockStatistics;
			lock (obj)
			{
				long dataMarkFromDateTime = this.GetDataMarkFromDateTime(DateTime.Now);
				bool flag2 = this.lastDataMark != dataMarkFromDateTime;
				if (flag2)
				{
					int times = (int)(dataMarkFromDateTime - this.lastDataMark);
					this.statistics = this.GetLeftMoveTimes(times);
					this.lastDataMark = dataMarkFromDateTime;
				}
				this.statistics[this.statistics.Length - 1] = newValue(this.statistics[this.statistics.Length - 1]);
			}
		}

		/// <summary>
		/// 新增一个统计信息，将会根据当前的时间来决定插入数据位置，如果数据位置发生了变化，则数据向左发送移动。如果没有移动或是移动完成后，最后一个数进行自定义的数据操作<br />
		/// Adding a new statistical information will determine the position to insert the data according to the current time. If the data position changes, 
		/// the data will be sent to the left. If there is no movement or after the movement is completed, Custom data operations on the last number
		/// </summary>
		/// <param name="newValue">增对最后一个数的自定义操作</param>
		/// <param name="time">增加的时间信息</param>
		// Token: 0x06001111 RID: 4369 RVA: 0x00061C04 File Offset: 0x0005FE04
		protected void StatisticsCustomAction(Func<T, T> newValue, DateTime time)
		{
			object obj = this.lockStatistics;
			lock (obj)
			{
				long dataMarkFromDateTime = this.GetDataMarkFromDateTime(DateTime.Now);
				bool flag2 = this.lastDataMark != dataMarkFromDateTime;
				if (flag2)
				{
					int times = (int)(dataMarkFromDateTime - this.lastDataMark);
					this.statistics = this.GetLeftMoveTimes(times);
					this.lastDataMark = dataMarkFromDateTime;
				}
				long dataMarkFromDateTime2 = this.GetDataMarkFromDateTime(time);
				bool flag3 = dataMarkFromDateTime2 <= dataMarkFromDateTime;
				if (flag3)
				{
					int num = (int)(dataMarkFromDateTime2 - (dataMarkFromDateTime - (long)this.statistics.Length + 1L));
					bool flag4 = num >= 0 && num < this.statistics.Length;
					if (flag4)
					{
						this.statistics[num] = newValue(this.statistics[num]);
					}
				}
			}
		}

		/// <summary>
		/// 获取当前的统计信息的数据快照，这是数据的副本，修改了里面的值不影响<br />
		/// Get a data snapshot of the current statistics. This is a copy of the data. Modifying the value inside does not affect
		/// </summary>
		/// <returns>实际的统计数据信息</returns>
		// Token: 0x06001112 RID: 4370 RVA: 0x00061CEC File Offset: 0x0005FEEC
		[HslMqttApi(Description = "Get a data snapshot of the current statistics")]
		public T[] GetStatisticsSnapshot()
		{
			return this.GetStatisticsSnapAndDataMark().Content2;
		}

		/// <summary>
		/// 根据指定的时间范围来获取统计的数据信息快照，包含起始时间，包含结束时间，这是数据的副本，修改了里面的值不影响<br />
		/// Get a snapshot of statistical data information according to the specified time range, including the start time, 
		/// also the end time. This is a copy of the data. Modifying the value inside does not affect
		/// </summary>
		/// <param name="start">起始时间</param>
		/// <param name="finish">结束时间</param>
		/// <returns>指定实际范围内的数据副本</returns>
		// Token: 0x06001113 RID: 4371 RVA: 0x00061D0C File Offset: 0x0005FF0C
		[HslMqttApi(Description = "Get a snapshot of statistical data information according to the specified time range")]
		public T[] GetStatisticsSnapshotByTime(DateTime start, DateTime finish)
		{
			bool flag = finish <= start;
			T[] result;
			if (flag)
			{
				result = new T[0];
			}
			else
			{
				object obj = this.lockStatistics;
				lock (obj)
				{
					long dataMarkFromDateTime = this.GetDataMarkFromDateTime(DateTime.Now);
					bool flag3 = this.lastDataMark != dataMarkFromDateTime;
					if (flag3)
					{
						int times = (int)(dataMarkFromDateTime - this.lastDataMark);
						this.statistics = this.GetLeftMoveTimes(times);
						this.lastDataMark = dataMarkFromDateTime;
					}
					long num = dataMarkFromDateTime - (long)this.statistics.Length + 1L;
					long num2 = this.GetDataMarkFromDateTime(start);
					long num3 = this.GetDataMarkFromDateTime(finish);
					bool flag4 = num2 < num;
					if (flag4)
					{
						num2 = num;
					}
					bool flag5 = num3 > dataMarkFromDateTime;
					if (flag5)
					{
						num3 = dataMarkFromDateTime;
					}
					int num4 = (int)(num2 - num);
					int num5 = (int)(num3 - num2 + 1L);
					bool flag6 = num2 == num3;
					if (flag6)
					{
						result = new T[]
						{
							this.statistics[num4]
						};
					}
					else
					{
						T[] array = new T[num5];
						for (int i = 0; i < num5; i++)
						{
							array[i] = this.statistics[num4 + i];
						}
						result = array;
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 获取当前的统计信息的数据快照，这是数据的副本，修改了里面的值不影响<br />
		/// Get a data snapshot of the current statistics. This is a copy of the data. Modifying the value inside does not affect
		/// </summary>
		/// <returns>实际的统计数据信息</returns>
		// Token: 0x06001114 RID: 4372 RVA: 0x00061E70 File Offset: 0x00060070
		public OperateResult<long, T[]> GetStatisticsSnapAndDataMark()
		{
			object obj = this.lockStatistics;
			OperateResult<long, T[]> result;
			lock (obj)
			{
				long dataMarkFromDateTime = this.GetDataMarkFromDateTime(DateTime.Now);
				bool flag2 = this.lastDataMark != dataMarkFromDateTime;
				if (flag2)
				{
					int times = (int)(dataMarkFromDateTime - this.lastDataMark);
					this.statistics = this.GetLeftMoveTimes(times);
					this.lastDataMark = dataMarkFromDateTime;
				}
				result = OperateResult.CreateSuccessResult<long, T[]>(dataMarkFromDateTime, this.statistics.CopyArray<T>());
			}
			return result;
		}

		/// <summary>
		/// 根据当前数据统计的时间模式，获取最新的数据标记信息<br />
		/// Obtain the latest data mark information according to the time mode of current data statistics
		/// </summary>
		/// <returns>数据标记</returns>
		// Token: 0x06001115 RID: 4373 RVA: 0x00061F04 File Offset: 0x00060104
		[HslMqttApi(Description = "Obtain the latest data mark information according to the time mode of current data statistics")]
		public long GetDataMarkFromTimeNow()
		{
			return this.GetDataMarkFromDateTime(DateTime.Now);
		}

		/// <summary>
		/// 根据指定的时间，获取到该时间指定的数据标记信息<br />
		/// According to the specified time, get the data mark information specified at that time
		/// </summary>
		/// <param name="dateTime">指定的时间</param>
		/// <returns>数据标记</returns>
		// Token: 0x06001116 RID: 4374 RVA: 0x00061F14 File Offset: 0x00060114
		[HslMqttApi(Description = "According to the specified time, get the data mark information specified at that time")]
		public long GetDataMarkFromDateTime(DateTime dateTime)
		{
			long result;
			switch (this.generateMode)
			{
			case GenerateMode.ByEveryMinute:
				result = this.GetMinuteFromTime(dateTime);
				break;
			case GenerateMode.ByEveryHour:
				result = this.GetHourFromTime(dateTime);
				break;
			case GenerateMode.ByEveryDay:
				result = this.GetDayFromTime(dateTime);
				break;
			case GenerateMode.ByEveryWeek:
				result = this.GetWeekFromTime(dateTime);
				break;
			case GenerateMode.ByEveryMonth:
				result = this.GetMonthFromTime(dateTime);
				break;
			case GenerateMode.ByEverySeason:
				result = this.GetSeasonFromTime(dateTime);
				break;
			case GenerateMode.ByEveryYear:
				result = this.GetYearFromTime(dateTime);
				break;
			default:
				result = this.GetDayFromTime(dateTime);
				break;
			}
			return result;
		}

		// Token: 0x06001117 RID: 4375 RVA: 0x00061FA4 File Offset: 0x000601A4
		private long GetMinuteFromTime(DateTime dateTime)
		{
			return (long)(dateTime.Date - new DateTime(1970, 1, 1)).Days * 24L * 60L + (long)(dateTime.Hour * 60) + (long)dateTime.Minute;
		}

		// Token: 0x06001118 RID: 4376 RVA: 0x00061FF0 File Offset: 0x000601F0
		private long GetHourFromTime(DateTime dateTime)
		{
			return (long)(dateTime.Date - new DateTime(1970, 1, 1)).Days * 24L + (long)dateTime.Hour;
		}

		// Token: 0x06001119 RID: 4377 RVA: 0x0006202C File Offset: 0x0006022C
		private long GetDayFromTime(DateTime dateTime)
		{
			return (long)(dateTime.Date - new DateTime(1970, 1, 1)).Days;
		}

		// Token: 0x0600111A RID: 4378 RVA: 0x0006205C File Offset: 0x0006025C
		private long GetWeekFromTime(DateTime dateTime)
		{
			return ((long)(dateTime.Date - new DateTime(1970, 1, 1)).Days + 3L) / 7L;
		}

		// Token: 0x0600111B RID: 4379 RVA: 0x00062090 File Offset: 0x00060290
		private long GetMonthFromTime(DateTime dateTime)
		{
			return (long)(dateTime.Year - 1970) * 12L + (long)(dateTime.Month - 1);
		}

		// Token: 0x0600111C RID: 4380 RVA: 0x000620AF File Offset: 0x000602AF
		private long GetSeasonFromTime(DateTime dateTime)
		{
			return (long)(dateTime.Year - 1970) * 4L + (long)((dateTime.Month - 1) / 3);
		}

		// Token: 0x0600111D RID: 4381 RVA: 0x000620CF File Offset: 0x000602CF
		private long GetYearFromTime(DateTime dateTime)
		{
			return (long)(dateTime.Year - 1970);
		}

		// Token: 0x0600111E RID: 4382 RVA: 0x000620E0 File Offset: 0x000602E0
		private T[] GetLeftMoveTimes(int times)
		{
			bool flag = times >= this.statistics.Length;
			T[] result;
			if (flag)
			{
				result = new T[this.arrayLength];
			}
			else
			{
				T[] array = new T[this.arrayLength];
				Array.Copy(this.statistics, times, array, 0, this.statistics.Length - times);
				result = array;
			}
			return result;
		}

		// Token: 0x0400045B RID: 1115
		private T[] statistics = null;

		/// <summary>
		/// 当前的实际模式
		/// </summary>
		// Token: 0x0400045C RID: 1116
		protected GenerateMode generateMode = GenerateMode.ByEveryDay;

		// Token: 0x0400045D RID: 1117
		private int arrayLength = 30;

		// Token: 0x0400045E RID: 1118
		private long lastDataMark = -1L;

		// Token: 0x0400045F RID: 1119
		private object lockStatistics;
	}
}
